from flask import Flask
app = Flask(__name__)
import requests
import os
import threading
import datetime
from time import time,sleep
import demjson

class server():
    def __init__(self):
        self.detector_list = []
        self.data_path = "static/data/"
        self.detector_apiport = 8088
        if os.path.exists(self.data_path+"ips/") == False:
            os.makedirs(self.data_path+"ips/")
        if os.path.exists(self.data_path + "success/") == False:
            os.makedirs(self.data_path + "success/")
        threading.Thread(target=self.check_alive).start()

    def save_file(self,filename,mode,content):
        '''
        一句话保存文件
        :param filename: 文件名
        :param mode: 模式
        :param content: 内容
        :return:
        '''
        f = open(filename,mode)
        f.write(content)
        f.close()

    def check_alive(self):
        '''
        检测当前探测器列表是否有超过30秒未上报状态的，检测到即删除
        :return:
        '''
        while True:
            for detector in self.detector_list:
                if time() - detector['report_time'] > 30:
                    self.detector_list.remove(detector)
                    self.save_file("static/log.txt", 'a+',
                                   "[{}]  Delete Detector IP {} ......\n".format(self.get_now_datetime(),
                                                                                 detector['ip']))
            sleep(1)
    def get_now_datetime(self):
        '''获取当前日期时间并格式化'''
        return datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')

    def splitList(self,parent_list, sublist_count):
        '''
        分割数组
        :param parent_list: 需要分割的数组
        :param sublist_count: 分割的数量
        :return: sublists 分割好的二维数据
        '''
        sub_lists = []
        remainder = len(parent_list) % sublist_count  # 余数
        n = parent_list[0:len(parent_list) - remainder]
        x = parent_list[len(n):len(parent_list)]
        avg = int(len(n) / sublist_count)
        for i in range(0, sublist_count):
            d = parent_list[avg * i:avg * (i + 1)]
            sub_lists.append(d)
        for i, ii in enumerate(x):
            sub_lists[i].append(ii)
        return sub_lists

    def assignments_ip(self,ip_path):
        '''
        分配IP到文件
        :param ipfile: 母IP文件
        :return:
        '''
        try:
            f = open(ip_path,'r')
            ip_list = f.read().split('\n')
            f.close()
            sublist_count = len(self.detector_list)
            print(self.detector_list)
            print(sublist_count)
            sub_lists = self.splitList(ip_list,sublist_count)
            for i,detector in enumerate(self.detector_list):
                filepath = "{}/{}.txt".format(self.data_path,detector['ip'])
                self.save_file(filepath,'w',"\n".join(sub_lists[i]))
                self.save_file("static/log.txt", 'a+',
                               "[{}]  Split IP File For {} : {}\n".format(self.get_now_datetime(), detector['ip'],
                                                                          filepath))
            return True
        except Exception as e:
            print("assignments_ip",e)
            return False
    def receive_report(self,report_info):
        '''
        接受上报信息
        参数：
        {
            "ip":"192.168.0.103",
            "status":"runing",
            "cpu":98,
            "mem":"485M",
            "start_time":"2019-7-4 20:46:21",
            "run_time":111447,
            "ping":"20ms",
            "match_count":50,
            "report_time":17782144741
        }
        :return:
        '''
        flag = False
        for detector in self.detector_list:
            if detector['ip'] == report_info['ip']:
                self.detector_list.remove(detector)
                self.detector_list.append(report_info)
                flag = True
                break
        if flag == False :
            self.detector_list.append(report_info)

    def success_report(self, success_info):
        try:
            fname = self.data_path + "success/" + success_info['task_id'] + "-" + success_info['data']['ip'] + ".html"
            self.save_file(fname, 'w', success_info['data']['resp'])
            return True
        except Exception as e:
            self.save_file("static/log.txt", 'a+',
                           "[{}]  Report Success Info Failed:{}\n".format(self.get_now_datetime(), e))
            return False
    def send_grab(self,detector,task_info):
        '''
        向所有主机发送抓取命令
        :return:
        '''
        api_url = "http://" + detector['ip'] + ":" + str(self.detector_apiport) + "/submit"
        # 加入IP
        task_info = demjson.decode(task_info)
        task_info['ip'] = detector['ip']
        task_info = demjson.encode(task_info)

        print("POST task_info:", task_info)
        try:
            response = requests.post(api_url,data={
                "task_info":task_info
            })
            if response.text.find("success") > -1:
                self.save_file("static/log.txt", 'a+',
                               "[{}]  Send Grab Command To {} Success......\n".format(self.get_now_datetime(), detector['ip']))
            else:
                self.save_file("static/log.txt", 'a+',
                               "[{}]  Send Grab Command To {} Failed , reason:{}\n".format(self.get_now_datetime(), detector['ip'],response.text))
        except Exception as e:
            self.save_file("static/log.txt", 'a+',
                           "[{}]  Send Grab Command To {} Error , Exception:{}\n".format(self.get_now_datetime(), detector['ip'],e))

    def send_grab_all(self,task_info):
        '''
        给所有的探测器发送grab指令
        :param task_info: grab参数 string json
        :return:
        '''
        try:
            info = demjson.decode(task_info)
            ip_path = self.data_path+"ips/"+info["ipfile"]
            if os.path.exists(ip_path) ==False:
                return {
                    "status":"failed",
                    "reason":"ip file not found"
                }
            if self.assignments_ip(ip_path)  == False:
                return {
                    "status": "failed",
                    "text": "Assignments IP Failed"
                }
            for detector in self.detector_list:
                threading.Thread(target=self.send_grab,args=(detector,task_info)).start()
            return {
                "status" :"success",
                "text":"send success"
            }
        except Exception as e:
            return {
                "status":"exceptiona",
                "reason":e
            }
    def stop(self,detector):
        '''
        停止单个探测器任务
        :param detector: 探测器
        :return:
        '''
        api_url = "http://" + detector['ip'] + ":"+ str(self.detector_apiport) + "/stop"
        try:
            response = requests.get(api_url)
            if response.text.find("success") > -1:
                self.save_file("static/log.txt", 'a+',
                               "[{}]  Stop Task {} Success...... \n".format(self.get_now_datetime(), detector['ip']))
            else:
                self.save_file("static/log.txt", 'a+',
                               "[{}]  Stop Task {} Failed : {}\n".format(self.get_now_datetime(), detector['ip'],
                                                                         response.text))

        except Exception as e:
            self.save_file("static/log.txt", 'a+',
                           "[{}]  Stop Task {} Exception : {}\n".format(self.get_now_datetime(), detector['ip'], e))
    def stop_all(self):
        for detector in self.detector_list:
            threading.Thread(target=self.stop,args=(detector,)).start()
